package ginv

import (
	"context"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"net/http"
	"reflect"
	"strings"
)

const (
	ByteName = "Data"
)

// WrapHandlerByte ...
func WrapHandlerByte(h interface{}) gin.HandlerFunc {
	if h == nil {
		panic("WrapHandler不能传入空")
	}
	t := reflect.TypeOf(h)
	if t.NumIn() < 3 {
		panic("入参必须填三个参数")
	}
	if reflect.TypeOf(h).Kind() != reflect.Func {
		panic("入参必须为函数")
	}
	if typeContext.AssignableTo(t.In(0)) && t.Out(0).AssignableTo(typeError) {
		return wrapByte31(reflect.ValueOf(h))
	}
	panic("未找到此函数")
}


func wrapByte31(hv reflect.Value) gin.HandlerFunc {
	t := hv.Type()
	return func(c *gin.Context) {
		var reqValue []reflect.Value
		var rspV reflect.Value
		defaultContext = c
		ctx = context.WithValue(c, RequestId, uuid.New().String())
		ctx, cancel := context.WithTimeout(ctx, DefaultGinTime)
		defer cancel()
		reqValue = append(reqValue, reflect.ValueOf(ctx))
		for i := 1; i < t.NumIn(); i++ {
			reqV, _ := inparam(c, t.In(i).Elem())
			reqValue = append(reqValue, reqV)
			if i == 2 {
				rspV = reqV
			}
		}
		out := hv.Call(reqValue)
		es, _ := out[0].Interface().(error)
		DefaultByteRspRender(c, rspV.Interface(), es)
	}
}


// DefaultByteRspRender 默认的请求结果处理函数
func DefaultByteRspRender(c *gin.Context, rsp interface{}, err error) {
	if err != nil {
		_ = c.Error(err)
		return
	}
	tl := reflect.TypeOf(rsp).Elem()
	vl := reflect.ValueOf(rsp).Elem()
	for i := 0; i < tl.NumField(); i++ {
		if tl.Field(i).Name == ByteName ||
			tl.Field(i).Tag.Get("json") == strings.ToLower(ByteName) {
			if tl.Field(i).Type.Kind() == reflect.Slice {
				c.Data(http.StatusOK,c.ContentType(),vl.Field(i).Interface().([]byte))
				return
			}
		}
	}
	c.Data(http.StatusOK,c.ContentType(),[]byte("返回参数类型不对"))
}